package tcp

import (
	"bufio"
	"context"
	"io"
	"my-godis/lib/logger"
	"my-godis/lib/sync/atomic"
	"my-godis/lib/sync/wait"
	"net"
	"sync"
	"time"
)

// EchoHandler echos received line to client, using for test
// 记录所有的活跃的链接 以及自身的状态
type EchoHandler struct {
	activateConn sync.Map
	closing      atomic.Boolean
}

// MakeEchoHandler creates EchoHandler
func MakeEchoHandler() *EchoHandler {
	return &EchoHandler{}
}

// EchoClient is client for EchoHandler, using for test
// 客户端与服务器的链接 waitgroup表示有多少个程序正在并发
type EchoClient struct {
	Conn    net.Conn
	Waiting wait.Wait
}

func (c *EchoClient) Close() error {
	// 全部执行完就退出  如果超过10秒 也强制退出了
	c.Waiting.WaitWithTimeout(10 * time.Second)
	// 这一步是等上面执行完了 即要么执行完 要么超时  则直接关闭
	c.Conn.Close()
	return nil
}

func (h *EchoHandler) Handle(ctx context.Context, conn net.Conn) {
	// 处理之前先看看这个handler活着没
	if h.closing.Get() {
		// 如果handler已经关闭 就把这个连接关了  不要新连进来了？  为啥？
		_ = conn.Close()
		// 那为啥不return？
		return
	}
	client := &EchoClient{
		Conn: conn,
	}
	h.activateConn.Store(client, struct{}{})

	// 使用bufio标准库提供的缓冲区功能 读连接的内容
	reader := bufio.NewReader(conn)
	for {
		// ReadString 会一直阻塞直到遇到分隔符'\n'
		// 遇到分隔符后会返回与上次的分隔符之间的数据  包括最后的分隔符本身
		//	如果读取异常 则处理
		msg, err := reader.ReadString('\n')
		// 处理错误
		if err != nil {
			if err == io.EOF {
				logger.Info("connection closed")
				h.activateConn.Delete(client)
			} else {
				logger.Warn(err)
			}
			return
		}
		// 任务开始 wg++
		client.Waiting.Add(1)
		b := []byte(msg)
		_, _ = conn.Write(b)
		// 写完了 done一下 wg--
		client.Waiting.Done()
	}
}

func (h *EchoHandler) Close() error {
	logger.Info("handler shutting down...")
	// 关闭
	h.closing.Set(true)
	h.activateConn.Range(func(key, value interface{}) bool {
		// 遍历所有的客户端 一个个关闭
		c := key.(*EchoClient)
		c.Close()
		// return true进行下一次遍历
		return true
	})
	return nil
}
